/*
 * Copyright 2012 Marsrutai.lt
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package lt.marsrutai.mobile.android.task;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import lt.marsrutai.mobile.android.AppContext;
import lt.marsrutai.mobile.android.activity.intent.TaskIntentHolder;
import lt.marsrutai.mobile.android.exception.DataAccessException;
import lt.marsrutai.mobile.android.model.MobileScope;
import lt.marsrutai.mobile.android.model.Schedule;
import lt.marsrutai.mobile.android.model.Track;
import lt.marsrutai.mobile.android.model.TrackBookmark;
import android.content.Intent;
import android.util.Log;
import android.util.Pair;

/**
 * Fetches bookmarked tracks
 * 
 * @author jvalskis
 */
public class GetTrackBookmarksTask extends NotifyingAsyncTask<Void, Void, Set<TrackBookmark>> {

    public static final String BROADCAST_ACTION = "lt.marsrutai.mobile.android.task.bookmarked_tracks";
    private static final String TAG = "GetTrackBookmarksTask";

    private Map<String, MobileScope> mobileScopes = new HashMap<String, MobileScope>();
    private Map<Pair<String, String>, Track> tracks = new HashMap<Pair<String, String>, Track>();
    private Map<Pair<String, String>, Schedule> schedules = new HashMap<Pair<String, String>, Schedule>();

    @Override
    protected Set<TrackBookmark> doInBackground(Void... params) {
        Set<TrackBookmark> storedTrackBookmarks = AppContext.getBookmarkService().getBookmarks(TrackBookmark.class);
        Iterator<TrackBookmark> iterator = storedTrackBookmarks.iterator();

        while (iterator.hasNext()) {
            TrackBookmark trackBookmark = (TrackBookmark) iterator.next();

            try {
                validateAndUpdateBookmark(trackBookmark);
            }
            catch (DataAccessException ex) {
                Log.i(TAG,
                        String.format("Unable to access data for scope: %s, trackId: %s.", trackBookmark.getScopeFolder(),
                                trackBookmark.getTrackId()));
                // TODO: delete invalid bookmarks, ex. tracks that no longer exist
                
                // do not display this bookmark - it does not contain the required information
                iterator.remove();
            }
        }
        return storedTrackBookmarks;
    }

    /**
     * Old format bookmarks do not store labels and other additional info,
     * therefore the info needs to be filled each time the bookmark is fetched
     * 
     * @param trackBookmark
     * @throws DataAccessException
     */
    private void validateAndUpdateBookmark(TrackBookmark trackBookmark) throws DataAccessException {
        boolean updated = false;
        String scope = trackBookmark.getScopeFolder();

        // track related properties
        if (trackBookmark.getTrackName() == null) {
            String trackId = trackBookmark.getTrackId();
            Track track = tracks.get(new Pair<String, String>(scope, trackId));
            if (track == null) {
                track = AppContext.getDataService().getTrackById(scope, trackId);
                tracks.put(new Pair<String, String>(scope, trackId), track);
            }
            trackBookmark.setTrackName(track.getName());
            trackBookmark.setScheduleId(track.getScheduleId());
            updated = true;
        }

        // schedule related properties
        if (trackBookmark.getScheduleName() == null || trackBookmark.getScheduleTrackName() == null) {
            String scheduleId = trackBookmark.getScheduleId();
            Schedule schedule = schedules.get(new Pair<String, String>(scope, scheduleId));
            if (schedule == null) {
                schedule = AppContext.getDataService().getScheduleById(scope, scheduleId);
                schedules.put(new Pair<String, String>(scope, scheduleId), schedule);
            }
            trackBookmark.setScheduleName(schedule.getName());
            trackBookmark.setScheduleTrackName(schedule.getTrackName());
            trackBookmark.setTransportId(schedule.getTransportId());
            updated = true;
        }

        // scope related properties
        if (trackBookmark.getScopeName() == null) {
            MobileScope mobileScope = mobileScopes.get(scope);
            if (mobileScope == null) {
                mobileScope = AppContext.getDataService().getScopeInfo(scope);
                mobileScopes.put(scope, mobileScope);
            }
            trackBookmark.setScopeName(mobileScope.getName());
            updated = true;
        }
        
        if (updated) {
            AppContext.getBookmarkService().updateBookmark(trackBookmark);
        }
    }

    @Override
    protected Intent getResultIntent(Set<TrackBookmark> result) {
        TaskIntentHolder intentHolder = new TaskIntentHolder(super.getResultIntent(result));
        intentHolder.setResult(result, TrackBookmark.class);
        return intentHolder.getIntent();
    }

    @Override
    protected String getBroadcastAction() {
        return BROADCAST_ACTION;
    }
}
